package com.zrx.govern.component.easyexcel.starter.utils;

import com.zrx.govern.component.easyexcel.starter.feign.entity.TreeEntity;
import org.apache.commons.collections4.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @Author: 10100
 * @License: (C) Copyright 2020-2050,  Corporation Limited.
 * @Contact: wang.he@cpe-smartcity.com
 * @Date: 2020/7/20 14:44
 * @Description: 构建树
 */
public class TreeBuilder<I, T extends TreeEntity<I, T>> {

    /**
     * 在循环每个node时 递归将每个node设置好了其子节点
     */
    private List<T> nodes;

    private String rootNodesId;

    public TreeBuilder(List<T> nodes) {
        this.nodes = nodes;
        this.rootNodesId = "0";
    }

    public TreeBuilder(List<T> nodes, String rootNodesId) {
        this.nodes = nodes;
        this.rootNodesId = rootNodesId;
    }

    /**
     * 构建树结构
     *
     * @return java.util.List<T>
     */
    public List<T> buildTree() {

        List<T> treeNodes = new ArrayList<>();
        List<T> rootNodes = this.getRootNodes();

        for (T rootNode : rootNodes) {
            this.buildChildNodes(rootNode);
            treeNodes.add(rootNode);
        }
        return treeNodes;

    }

    /**
     * 递归子节点
     *
     * @param node 节点
     * @return void
     */
    private void buildChildNodes(T node) {
        List<T> children = this.getChildNodes(node);

        if (CollectionUtils.isNotEmpty(children)) {
            for (T child : children) {
                buildChildNodes(child);
            }
            node.setChildren(children);
        }
    }


    /**
     * 获取父节点下一级所有子节点
     * @param pNode 父节点
     * @return java.util.List<T>
     */
    private List<T> getChildNodes(T pNode) {
        List<T> childNodes = new ArrayList<>();
        for (T n : nodes) {
            if (pNode.getId().equals(n.getParentId())) {
                childNodes.add(n);
            }
        }
        return childNodes;
    }

    /**
     * 获取父节点下一级所有子节点
     * @param pId 父节点id
     * @return java.util.List<T>
     */
    private List<I> getChildNodes(I pId) {
        List<I> childNodes = new ArrayList<>();
        for (T n : nodes) {
            if (pId.equals(n.getParentId())) {
                childNodes.add(n.getId());
            }
        }
        return childNodes;
    }

    /**
     * 获取父节点下所有子节点
     * @param pId 父节点id
     * @return java.util.List<T>
     */
    public List<I> getAllChildNodes(I pId) {
        List<I> allchildNodes = new ArrayList<>();
        recurrenceAllChildNodes(allchildNodes, pId);
        return allchildNodes;
    }

    /**
     * @param allchildNodes:
     * @param pId:
     * @desc: 递归获取所有子节点
     * @return: void
     **/
    private void recurrenceAllChildNodes(List<I> allchildNodes, I pId) {
        List<I> children = this.getChildNodes(pId);
        if (CollectionUtils.isNotEmpty(children)) {
            for (I child : children) {
                allchildNodes.add(child);
                recurrenceAllChildNodes(allchildNodes, child);
            }
        }
    }


    /**
     * 获取父节点下所有子节点
     * @param pNode 父节点
     * @return java.util.List<T>
     */
    public List<T> getAllChildNodes(T pNode) {
        List<T> allchildNodes = new ArrayList<>();
        recurrenceAllChildNodes(allchildNodes, pNode);
        return allchildNodes;
    }

    /**
     * @param allchildNodes:
     * @param node:
     * @desc: 递归获取所有子节点
     * @return: void
     **/
    private void recurrenceAllChildNodes(List<T> allchildNodes, T node) {
        List<T> children = this.getChildNodes(node);
        if (CollectionUtils.isNotEmpty(children)) {
            for (T child : children) {
                allchildNodes.add(child);
                recurrenceAllChildNodes(allchildNodes, child);
            }
        }
    }

    /**
     * 获取当前节点所有父节点
     * @param pNode 父节点
     * @return java.util.List<T>
     */
    public List<T> getAllParentNodes(T pNode) {
        List<T> allchildNodes = new ArrayList<>();
        recurrenceAllParentNodes(allchildNodes, pNode);
        return allchildNodes;
    }

    public void recurrenceAllParentNodes(List<T> allchildNodes, T pNode) {
        for (T node : nodes) {
            if (node.getId().equals(pNode.getParentId())) {
                allchildNodes.add(node);
                if(!rootNodesId.equals(pNode.getParentId())){
                    recurrenceAllParentNodes(allchildNodes, node);
                }
            }
        }
    }



    /**
     * 判断是否为根节点
     * @param node 节点
     * @return boolean
     */
    private boolean rootNode(T node) {
        boolean isRootNode = false;
        if (rootNodesId.equals(node.getParentId().toString())) {
            isRootNode = true;
        }
        return isRootNode;
    }

    /**
     * 获取所有最小子节点
     * @return
     */
    public List<T> findAllMinChildNode() {
        List<T> rootNodes = new ArrayList<>();
        for (T node : nodes) {
            AtomicBoolean flag = new AtomicBoolean(false);
            nodes.forEach(el -> {
                if (node.getId().equals(el.getParentId().toString())) {
                    flag.set(true);
                }
            });
            if (!flag.get()) {
                rootNodes.add(node);
            }
        }
        return rootNodes;
    }

    /**
     * 获取所有根节点
     *
     * @return java.util.List<T>
     */
    private List<T> getRootNodes() {
        List<T> rootNodes = new ArrayList<>();
        for (T n : nodes) {
            if (rootNode(n)) {
                rootNodes.add(n);
            }
        }
        return rootNodes;
    }
}
